
using UnityEngine;
using UnityEngine.Scripting;
using WooEngine.Persistence;
using WooEngine.Persistence.Provider;
using Object = UnityEngine.Object;

namespace WooEngine.Audio.Provider
{
    [Preserve]
    public class BgmProvider : IAudioProvider
    {
        public struct BgmParams
        {
            public bool playOnAwake;
        }


        public enum State
        {
            Stop,
            Pause,
            Playing,
        }

        public bool IsPlaying => false;
        public float Volume { get => audioSource.volume; }
        public float VolumeMax { get => 1; }
        public bool IsOn { get => m_IsOn; }

        private string providerTag;
        private string dbTag;
        private bool m_IsOn;
        private AudioSource audioSource;


        [Preserve]
        public BgmProvider(string tag, bool isOn, float volume, object audioData)
        {

            providerTag = tag;
            dbTag = StringUtils.AppendString("audio_db_", tag);
            DBManager.Instance.CreateProvider<EasySaveProvider>(dbTag, dbTag);

            audioSource = new GameObject(tag).AddComponent<AudioSource>();
            audioSource.loop = true;
            audioSource.transform.SetParent(AudioManager.Instance.transform, false);

            if (DBManager.Instance.IsHasDB(tag))
            {
                audioSource.volume = DBManager.Instance.Load<float>(tag, "Volume");
                m_IsOn = DBManager.Instance.Load<bool>(tag, "IsOn");
                audioSource.playOnAwake = DBManager.Instance.Load<bool>(tag, "PlayOnAwake");
            }
            else
            {
                Switch(isOn);
                SetVolume(volume);
                SetAudioData(audioData);
            }
        }


        public void Play(AudioClip clip, object userdata)
        {
            if (audioSource.clip != clip)
            {
                if (audioSource.isPlaying)
                {
                    audioSource.Stop();
                }
                if (audioSource.clip != null)
                {
                    var clip_old = audioSource.clip;
                    Res.ResourceManager.Instance.ReleaseAsset(clip_old);
                    audioSource.clip = null;
                }
                audioSource.clip = clip;
                if (IsOn)
                {
                    audioSource.Play();
                }
            }

        }

        public void Release()
        {
            if (audioSource != null)
            {
                if (audioSource.isPlaying)
                {
                    audioSource.Stop();
                }
                if (audioSource.clip != null)
                {
                    var clip_old = audioSource.clip;
                    Res.ResourceManager.Instance.ReleaseAsset(clip_old);
                    audioSource.clip = null;
                }
                Object.Destroy(audioSource);
            }
        }

        public void Pause()
        {
            if (IsOn)
            {
                audioSource.Pause();
            }
        }

        public void Resume()
        {
            if (IsOn)
            {
                audioSource.UnPause();
            }
        }

        public void Stop()
        {
            audioSource.Stop();
            audioSource.time = 0;
        }


        public void Switch(bool isOn)
        {
            m_IsOn = isOn;
            if (!isOn)
            {
                Stop();
            }
            DBManager.Instance.Save<bool>(dbTag, "IsOn", m_IsOn);
        }

        public void SetVolume(float volume)
        {
            audioSource.volume = volume;
            DBManager.Instance.Save<float>(dbTag, "Volume", audioSource.volume);
        }

        public void SetAudioData(object audioData)
        {
            if (audioData is BgmParams param)
            {
                audioSource.playOnAwake = param.playOnAwake;
                DBManager.Instance.Save<bool>(dbTag, "PlayOnAwake", param.playOnAwake);
            }
        }
    }
}
